/*
 * Copyright 2014 Geoff Capper.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package gmapsfx.javascript.event;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import netscape.javascript.JSObject;

/** This object forms the bridge between Javascript events and the Java events.
 * <p>
 * An instance of this class is assigned to the document model so that 
 * Javascript can access it to make callbacks when events occur.
 * <p>
 * An application calls on one of the two addXXEventHandler methods in the 
 * {@link gmapsfx.javascript.object.GoogleMap} class to register an 
 * instance of the {@link GFXEventHandler} interface against a certain event 
 * type in the Google Maps event model. See addUIEventHandler and addStateEventHandler.
 * <p>
 * This class uses a key based on a UUID to map the Javascript event handlers 
 * registered against the Google Maps model back to our Java event handlers 
 * stored here. The addXXEventHandler methods in GoogleMap create functions 
 * that call back into this class using the supplied key.
 * <p>
 * Currently an instance of this class is registered as:
 * <code>document.jsHandlers</code>
 * <p>
 * The event listeners are established using the following Javascript calls:
 * <p>
 * {@link gmapsfx.javascript.object.GoogleMap#addUIEventHandler}
 * <p><blockquote><pre><code>
 * google.maps.event.addListener(map, 'event_type', function(event) {
 *      document.jsHandlers.handleUIEvent('key', event.latLng);
 * });
 * </code></pre></blockquote>
 * <p>
 * {@link gmapsfx.javascript.object.GoogleMap#addStateEventHandler}
 * <p><blockquote><pre><code>
 *  google.maps.event.addListener(map, 'event_type', function() {
 *      document.jsHandlers.handleStateEvent('key');
 *  });
 * </code></pre></blockquote>
 * 
 * @author Geoff Capper
 * 
 */
public class EventHandlers {
	
	private final Map<String, GFXEventHandler> handlers = new HashMap<>();
    
	public EventHandlers() {
	}
	
	/** Registers a handler and returns the callback key to be passed to 
	 * Javascript.
	 * 
	 * @param handler Handler to be registered.
	 * @return A String random UUID that can be used as the callback key.
	 */
	public String registerHandler(GFXEventHandler handler) {
		String uuid = UUID.randomUUID().toString();
		handlers.put(uuid, handler);
		return uuid;
	}
	
    /** This method is called from Javascript, passing in the previously 
     * created callback key, and the event object. The current implementation 
     * is receiving the LatLng object that the Javascript MouseEvent contains. 
     * <p>
     * It may be more useful to return the MouseEvent and let clients go from 
     * there, but there is only the stop() method on the MouseEvent?
     * 
     * @param callbackKey Key generated by the call to registerHandler.
     * @param result Currently the LatLng object from the Google Maps event.
     */
	public void handleUIEvent(String callbackKey, JSObject result) {
		if (handlers.containsKey(callbackKey) && handlers.get(callbackKey) instanceof UIEventHandler) {
			((UIEventHandler) handlers.get(callbackKey)).handle(result);
		} else {
			System.err.println("Error in handle: " + callbackKey + " for result: " + result);
		}
	}
    
    /** This method is called from Javascript, passing in the previously 
     * created callback key. It uses that to find the correct handler and 
     * then passes on the call. State events in the Google Maps API don't pass 
     * any parameters.
     * 
     * @param callbackKey Key generated by the call to registerHandler.
     */
    public void handleStateEvent(String callbackKey) {
		if (handlers.containsKey(callbackKey) && handlers.get(callbackKey) instanceof StateEventHandler) {
			((StateEventHandler) handlers.get(callbackKey)).handle();
		} else {
			System.err.println("Error in handle: " + callbackKey + " for state handler ");
		}
	}
	
}